#pragma once

#include "Render/Widget/RenderWidgets.h"
#include "Render/PreRender/PreRenderWidgets.h"
#include "Render/Widget/VulkanRectWidget.h"
#include "Render/Widget/VulkanCircleWidget.h"
#include "Render/Widget/VulkanRingWidget.h"
#include "Render/Widget/VulkanImageWidget.h"
#include "Render/Widget/VulkanTextWidget.h"
#include "Render/Widget/VulkanStaticTextWidget.h"
#include "Render/Widget/VulkanLineWidget.h"
#include "Render/Widget/VulkanTriangleWidget.h"
#include "Render/Widget/VulkanViewportWidget.h"

class CVulkanWindow
{
public:   
    CVulkanWindow(vk::SurfaceKHR InVKSurface);
    ~CVulkanWindow();

    vk::SurfaceKHR GetVKSurface();

    uint8_t GetSwapChainImageCount();

    vk::CommandBuffer GetPrimaryCommandBuffer();

    vk::Framebuffer GetCurrentFrameBuffer();

    vk::Extent2D GetSwapChainImageSize();

    vk::Image GetCurrentSwapChainImage();


protected:
    uint64_t WindowHandle;

    vk::SurfaceKHR VKSurface;

    vk::PresentModeKHR SurfacePresentMode;

    vk::CommandBuffer ClearImageBuffer; //first command buffer to clear swapchain image
    vk::CommandBuffer PrimaryCommandBuffer;

    vk::SwapchainKHR VKSwapChain;
    uint8_t SwapChainImageCount;
    vk::Extent2D SwapChainImageSize;
    void UpdateSwapChain();

    TVector<vk::Image> SwapchainImage;
    TVector<vk::ImageView> SwapchainImageViews;  
    void UpdateSwapchainImageAndImageViews();

    vk::Image DepthImage;
    vk::ImageView DepthView;
    vk::DeviceMemory DepthMemory;
    void UpdateDepthImageAndImageView();

    //clear surface and init images' layout
    vk::RenderPass ClearRenderPass;
    void UpdateClearRenderPass();

    //convert swapchain image layout to present layout
    vk::RenderPass PresentRenderPass;
    void UpdatePresentRenderPass();

    //frame buffer for Present render pass
    TVector<vk::Framebuffer> PresentFrameBuffers;
    void UpdatePresentFrameBuffers();



    TVector<vk::Framebuffer> FrameBuffers;
    void UpdateFrameBuffers();

    vk::Semaphore PresentWaitSemaphore; 
    vk::Semaphore ImageAvailableSemaphore;
    void UpdateRenderSemaphores();

    vk::Fence RenderFence;
    void UpdateFence();

    void OnSwapChainResized();
public:

    void PrepareFrame();

    void WaitFormerFrame();

    void PrepareRecord(const SPreRenderWidgets& Widgets);

    void CreateRecordTasks();

    void RecordPrimaryCommandBuffer();

    bool RecordNothing();

    void Submit();

    void PresentFrame();

    //void RenderFrame();
protected:
    bool bNeedRebuildSwapChain = false;
    uint32_t CurrentFrame=0;

    //make sure acquire only one image before present 
    //if not,  cause vulkan validation error
    bool bNeedRequireImage = true;

    bool bNeedWaitFormerFrame = true;

    SRenderCommandBuffers SecondaryCommandBuffers;

protected:
    CVulkanRectWidgets RectPainter[2];
    CVulkanCircleWidgets CirclePainter[2];
    CVulkanRingWidgets  RingPainter[2];
    CVulkanImageWidgets ImagePainter[2];
    CVulkanTextWidgets TextPainter[2];
    CVulkanStaticTextWidgets StaticTextPainter[2];
    CVulkanLineWidgets LinePainter[2];
    CVulkanTriangleWidgets TrianglePainter[2];
    CVulkanViewportWidgets ViewportPainter[2];    

};